//
//  publicTableHeader.cc
//  
//
//  Created by Henklajd on 4/8/13.
//
//

#include "publicTableHeader.h"
#include "ns3/assert.h"
#include "ns3/log.h"
#include "ns3/header.h"
#include "ns3/simulator.h"
#include <vector>

NS_LOG_COMPONENT_DEFINE ("PublicTableHeader");

namespace ns3 {
    
    
    NS_OBJECT_ENSURE_REGISTERED (PublicTableHeader);
    PublicTableHeader::PublicTableHeader()
    {
        NS_LOG_FUNCTION (this);
    }
    
    
    PublicTableHeader::PublicTableHeader (std::vector<FileInfo> pubTab,uint8_t cas):pubTable(pubTab),cases(cas)
    {
        NS_LOG_FUNCTION (this);
    }
    
    /*
     void
     SeqTsHeader::SetSeq (uint32_t seq)
     {
     NS_LOG_FUNCTION (this << seq);
     m_seq = seq;
     }
     uint32_t
     SeqTsHeader::GetSeq (void) const
     {
     NS_LOG_FUNCTION (this);
     return m_seq;
     }
     
     Time
     SeqTsHeader::GetTs (void) const
     {
     NS_LOG_FUNCTION (this);
     return TimeStep (m_ts);
     }
     */
    
    std::vector<FileInfo> PublicTableHeader::GetData()
    {
        
        return pubTable;
    }
    
    TypeId
    PublicTableHeader::GetTypeId (void)
    {
        static TypeId tid = TypeId ("ns3::PublicTableHeader")
        .SetParent<Trailer> ()
        .AddConstructor<PublicTableHeader> ()
        ;
        return tid;
    }
    TypeId
    PublicTableHeader::GetInstanceTypeId (void) const
    {
        return GetTypeId ();
    }
    void
    PublicTableHeader::Print (std::ostream &os) const
    {
        NS_LOG_FUNCTION (this << &os);
        // os << "(seq=" << m_seq << " time=" << TimeStep (m_ts).GetSeconds () << ")";
    }
    uint32_t
    PublicTableHeader::GetSerializedSize (void) const
    {
        NS_LOG_FUNCTION (this);
        uint32_t size=4;
        for(uint32_t i=0;i<pubTable.size();i++)
        {
            size+=4;
            size+=(pubTable[i].fileName).length();
            size+=4;
            size+=((pubTable[i].occurrences).size())*8;
        }
        
        return size+1;
    }
    
    void
    PublicTableHeader::Serialize (Buffer::Iterator start) const
    {
        NS_LOG_FUNCTION (this << &start);
        Buffer::Iterator j = start;
        j.Prev(GetSerializedSize());
        
        // Invia info frame information size
        
        j.WriteU8(cases);
        j.WriteU32(pubTable.size());
        
        for(unsigned k=0;k<pubTable.size();k++)
        {
            j.WriteU32(pubTable[k].fileName.length());
            
            for ( unsigned i=0; i<pubTable[k].fileName.length(); i++)
            {
                
                j.WriteU8((uint8_t)(pubTable[k].fileName.at(i)));
                
            }
            
            j.WriteU32(pubTable[k].occurrences.size());
            
            for (std::map<uint32_t,uint32_t>::const_iterator it=(pubTable[k].occurrences).begin(); it!=(pubTable[k].occurrences).end(); ++it)
            {j.WriteU32(it->first); j.WriteU32(it->second);}
            
        }
    }
    
    
    
    uint32_t
    PublicTableHeader::Deserialize (Buffer::Iterator start)
    {
        NS_LOG_INFO (this << &start);
        
        Buffer::Iterator j = start;
        //std::cout<<"§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§"<<std::endl;

        while(!j.IsStart())
            j.Prev();
        
        cases=j.ReadU8();
        uint32_t pubTabSize=j.ReadU32();
        //std::cout<<"***pubTabSize*** "<<pubTabSize<<std::endl;
        uint32_t mapSize=0;
        for ( uint32_t k=0; k<pubTabSize; k++) 
        { uint32_t length=j.ReadU32();
            std::string str;
            for(uint32_t i=0;i<length;i++)
            {str+=(char)j.ReadU8();}
            
            mapSize=j.ReadU32();
           
            if(mapSize!=0){
          //      std::cout<<"***mapSize*** "<<mapSize<<std::endl;
            std::map<uint32_t,uint32_t> map;
            uint32_t node=j.ReadU32();
            map[node]=j.ReadU32();
            
            pubTable.push_back(FileInfo(str,map));
            
            for(uint32_t l=1;l<mapSize;l++)
            {   node=j.ReadU32();
                pubTable[k].occurrences.insert(std::pair<uint32_t,uint32_t>(node,j.ReadU32()));
            }
            }
        }
        
        
        return GetSerializedSize ();
    }
    
} // namespace ns3
